<?php

namespace App\Jobs;

use App\Model\Account;
use App\Model\Coin;
use App\Model\Trade;
use App\Model\TradeLog;
use App\Traits\TradeQueue;
use DB;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class MatchTrading implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, TradeQueue;

    protected $coinId;

    /**
     * Create a new job instance.
     *
     * @param Trade $trade
     */
    public function __construct(Trade $trade)
    {
        $this->coinId = $trade->coin_id;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $buy  = $this->getBuy($this->coinId);
        $sell = $this->getSell($this->coinId);
        if (! $buy || ! $sell) {
            return;
        }
        if ($buy->peice < $sell->price) {
            return;
        }
        $buyNumber  = $buy->number - $buy->deal;
        $sellNumber = $sell->number - $sell->deal;
        //交易数量
        $number = min($buyNumber, $sellNumber);

        if ($buy->id > $sell->id) {
            //交易类型
            $type = 1;
            //交易价格
            $price = $sell->price;
        } else {
            $type  = 0;
            $price = $buy->price;
        }
        //交易额
        $money = $price * $number;

        $coin = Coin::where('id', $this->coinId)->first();
        //买家支付帐户
        $buyPayAccount = Account::where('coin_id', $coin->pay_coin_id)->where('user_id', $buy->user_id)->first();
        //买家虚拟币帐户
        $buyAccount = Account::where('coin_id', $coin->id)->where('user_id', $buy->user_id)->first();
        //卖家虚拟币帐户
        $sellAccount = Account::where('coin_id', $coin->id)->where('user_id', $sell->user_id)->first();
        //卖家支付帐户
        $sellPayAccount = Account::where('coin_id', $coin->pay_coin_id)->where('user_id', $sell->user_id)->first();
        //买入手续费
        if ($buyAccount->buy_fee == 0) {
            $buy_fee = $money * $coin->buy_fee / 100;
        } else {
            $buy_fee = $money * $buyAccount->buy_fee / 100;
        }
        //卖出手续费
        if ($sellAccount->sell_fee == 0) {
            $sell_fee = $money * $coin->sell_fee / 100;
        } else {
            $sell_fee = $money * $sellAccount->sell_fee / 100;
        }
        //买卖交易量全部成交，修改订单状态为完成
        $buy->deal += $number;
        if ($buy->deal == $buy->number) {
            $buy->status = 1;
        }
        $sell->deal += $number;
        if ($sell->deal == $sell->number) {
            $sell->status = 1;
        }
        //买卖交易成交，买价高于成交价，则返还差价
        $different = 0;
        if ($buy->price > $price) {
            if ($buyAccount->buy_fee == 0) {
                $different = $number * ($buy->price - $price) * (1 + $coin->buy_fee / 100);
            } else {
                $different = $number * ($buy->price - $price) * (1 + $buyAccount->buy_fee / 100);
            }
        }
        //生成记录
        $tradeLog             = new TradeLog();
        $tradeLog->buyer      = $buy->user_id;
        $tradeLog->seller     = $sell->user_id;
        $tradeLog->buy_trade  = $buy->id;
        $tradeLog->sell_trade = $sell->id;
        $tradeLog->coin_id    = $coin->id;
        $tradeLog->type       = $type;
        $tradeLog->price      = $price;
        $tradeLog->number     = $number;
        $tradeLog->buy_fee    = $buy_fee;
        $tradeLog->sell_fee   = $sell_fee;

        try {
            DB::transaction(function () use ($tradeLog, $buy, $sell, $different, $number, $buyAccount, $buyPayAccount, $sellAccount, $sellPayAccount, $money, $buy_fee, $sell_fee) {
                $tradeLog->save();
                $buy->save();
                $sell->save();
                //买家虚拟币增加
                $buyAccount->increment('available', $number);
                //卖家虚拟币减少
                $sellAccount->decrement('disabled', $number);
                //买家支付币减少
                $buyPayAccount->decrement('disabled', $money + $buy_fee);
                //卖家支付币增加
                $sellPayAccount->increment('available', $money - $sell_fee);
                //有差价，则返还
                if ($different) {
                    $buyPayAccount->enable($different);
                }
            });

        } catch (Exception $exception) {
            return;
        }
        //从队列中移除已经完全成交的买卖交易
        if ($buy->status == 1) {
            $this->removeBuy($this->coinId, $buy->id);
        }
        if ($sell->status == 1) {
            $this->removeSell($this->coinId, $sell->id);
        }
        $this->handle();
    }
}
